package org.duang.proxy;

import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

import org.apache.curator.framework.recipes.locks.InterProcessLock;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.duang.aop.Proxy;
import org.duang.aop.ProxyChain;
import org.duang.ioc.Lock;
import org.duang.lock.ZkSyncLock;

/**
 * 用于分布式锁
 * 注： 每一个代理注解只能用于一个方法上，如需要进行多个代理执行操作，可以将service里的method细粒度化
 * @author laotang
 */
public class LockProxy implements Proxy {
	
	private String name;
	private InterProcessLock lock;
	private long waitTimeout;
	
	public Object doProxy(ProxyChain proxyChain) throws Exception {
		Object resultObj = null;
		Class<?> cls = proxyChain.getTargetClass();
		Method method = proxyChain.getTargetMethod();
		Object[] params = proxyChain.getMethodParams();
		if(method.isAnnotationPresent(Lock.class)){
			before(cls, method, params);
			if(!lock.acquire(waitTimeout, TimeUnit.SECONDS)) {
				throw new IllegalStateException( name + " wait " + waitTimeout + " seconds, catn't get to lock, give up...");
			}
			try{
				resultObj = proxyChain.doProxyChain();
				System.out.println(name + "正在执行----------");
			} finally {
				lock.release();		//释放锁
			}
			after(cls, method, params, resultObj);
		} else {
			resultObj = proxyChain.doProxyChain();
		}
		return resultObj;
	}

	public void before(Class<?> cls, Method method, Object[] params) throws Exception {
		this.name = "lockJob_"+ System.currentTimeMillis();
		this.lock = new InterProcessMutex(ZkSyncLock.getCuratorFramework(), ZkSyncLock.getRootPath());
		this.waitTimeout = ZkSyncLock.getWaitTimeout();
		System.out.println(name + "开始执行----------");
	}
	
	public void after(Class<?> cls, Method method, Object[] params, Object result) throws Exception {
		if(lock != null) lock = null;
		System.out.println(name + "结束执行----------");
	}
	
}
